package cn.bugstack.domain.strategy.service.armory;

import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Title: StrategyArmory
 * @Author lz
 * @Date 2025/7/23 20:52
 * @description: 策略装配库，负责初始化策略计算
 */
@Slf4j
@Service
public class StrategyArmory implements IStrategyArmory{

    @Resource
    private IStrategyRepository strategyRepository;
    @Override
    public void assembleLotteryStrategy(Long strategyId) {
        //查询策略配置
       List<StrategyAwardEntity> strategyAwardEntityList= strategyRepository.queryStrategyAwardList(strategyId);
       //获取最小概率值
        BigDecimal minAwardRate = strategyAwardEntityList.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);
        if (minAwardRate.compareTo(BigDecimal.ZERO) == 0) {
            log.warn("策略ID：{}，最小概率值为0，可能导致除零异常", strategyId);
            // 可抛出自定义异常或设置最小默认值，如：
            minAwardRate = BigDecimal.valueOf(0.0001); // 设置一个极小值防止除零
        }
        //获取概率值总和
        BigDecimal totalAwardRate = strategyAwardEntityList.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .reduce(BigDecimal.ZERO,BigDecimal::add);//TODO 数据量太大，考虑分批次处理
        //用 1 % 0.0001 获得概率范围，百分位、千分位、万分位
        BigDecimal tem=BigDecimal.valueOf(0.01);
        BigDecimal rateRange = tem.divide(minAwardRate, 0, RoundingMode.CEILING);
        //生成策略奖品概率查询表，存放对应的奖品占位，占位越高概率越高
        List<Integer> strategyRateTables=new ArrayList<>(rateRange.intValue());
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntityList){//对于每一个奖品的操作
            Integer awardId = strategyAwardEntity.getAwardId();
            BigDecimal awardRate = strategyAwardEntity.getAwardRate();
            //计算每个概率需要存放到查找表的位置
            for (int i=0 ;i<awardRate.multiply(rateRange).intValue() ; i++){
                strategyRateTables.add(awardId);
            }
        }
        //乱序
        Collections.shuffle(strategyRateTables);
        //生成map集合，key对应的就是后续的概率值，通过概率获得对应的奖品
        Map<Integer, Integer> suffleStrategyRateTables = new HashMap<>();
        for (int i=0;i<strategyRateTables.size();i++){
            suffleStrategyRateTables.put(i, strategyRateTables.get(i));
        }
        //将map存放在redis中
        strategyRepository.storeStrateAwardSearchTable(strategyId,suffleStrategyRateTables.size(),suffleStrategyRateTables);


        //TODO 权重策略配置，适用于rule_weight 权重规则配置
    }

    @Override
    public Integer getRandomAwardId(Long strategyId) {
        // 分布式部署下，不一定为当前应用做的策略装配。也就是值不一定会保存到本应用，而是分布式应用，所以需要从 Redis 中获取。
        Integer rateRange = strategyRepository.getRateRange(strategyId);
        return strategyRepository.getStrategyAwardAssemble(strategyId, ThreadLocalRandom.current().nextInt(0, rateRange + 1));
    }

}
